package biz.inspeed.test.io;

import java.security.SecureRandom;

public class BytesUtil
{
	private static SecureRandom	rng;

	/** 获取id的byte数组，UUID的byte形式 **/
	public static byte [ ] getID ()
	{
		byte [ ] data;// = new byte[16];
		synchronized ( BytesUtil.class )
		{
			if ( rng == null )
			{
				rng = new SecureRandom ();
			}
		}
		rng.nextBytes ( data = new byte [ 16 ] );
		return data;
	}

	/** 将Head序列化为byte数组 (32个字节)**/
	public static byte [ ] toByte ( Head head )
	{
		byte [ ] rv = new byte [ 32 ];
		byte [ ] bytes = getIntBytes ( head.messageLength );
		///消息的长度
		System.arraycopy ( bytes , 0 , rv , 0 , 4 );
		///commandNum
		bytes = getIntBytes ( head.commandNum );
		System.arraycopy ( bytes , 0 , rv , 4 , 4 );
		
		///commandLevel
		bytes = getIntBytes ( head.commandLevel );
		System.arraycopy ( bytes , 0 , rv , 8 , 4 );
		///transactId
		bytes = head.transactId;
		System.arraycopy ( bytes , 0 , rv , 12 , 16 );
		///serialNum
		bytes = getIntBytes ( head.serialNum );
		System.arraycopy ( bytes , 0 , rv , 28 , 4 );
		return rv;
	}
	
	public static Head fromBytes(byte[] bytes){
		if(bytes.length != 32){
			throw new IllegalArgumentException ( "传入的参数不对！长度应该是 32，您传入的byte数组的长度是" +bytes.length );
		}
		Head head = new Head ();
		byte[] b = new byte[4];
		b = new byte[]{bytes[0],bytes[1],bytes[2],bytes[3]};
		int data = getInt ( b );
		/// 可以增加对头信息的一些验证
		head.messageLength = data;
		if(data< 0)
		{
			throw new IllegalArgumentException ( "传入的参数不对！"  );
		}
		b = new byte[]{bytes[4],bytes[5],bytes[6],bytes[7]};
		data = getInt ( b );
		if(data< 10000)
		{
			throw new IllegalArgumentException ( "传入的参数不对！"  );
		}
		head.commandNum = data;
		b = new byte[]{bytes[8],bytes[9],bytes[10],bytes[11]};
		data = getInt ( b );
		if(data< 19876000)
		{
			throw new IllegalArgumentException ( "传入的参数不对！"  );
		}
		head.commandLevel = data;
		
		byte[] bid = new byte[16];
		System.arraycopy ( bytes , 12 , bid , 0 , 16 );
		
		head.transactId = bid;
		System.arraycopy ( bytes , 28 , b , 0 , 4 );
		data = getInt ( b );
		if(data< 0)
		{
			throw new IllegalArgumentException ( "传入的参数不对！"  );
		}
		head.serialNum = data;
		return head;
	}

	public static int getInt ( byte [ ] bytes )
	{
		if ( bytes == null || bytes.length != 4 )
		{
			return 0;// throw new RuntimeException("类型不对!");
		}
		return ( ( bytes [ 0 ] & 0xff ) << 24 ) | ( ( bytes [ 1 ] & 0xff ) << 16 )
				| ( ( bytes [ 2 ] & 0xff ) << 8 ) | ( bytes [ 3 ] & 0xff );
	}

	public static byte [ ] getIntBytes ( int value )
	{
		byte [ ] bytes = new byte [ 4 ];
		bytes [ 0 ] = ( byte ) ( value >> 24 & 0xff );
		bytes [ 1 ] = ( byte ) ( value >> 16 & 0xff );
		bytes [ 2 ] = ( byte ) ( value >> 8 & 0xff );
		bytes [ 3 ] = ( byte ) ( value & 0xff );
		return bytes;
	}

	public static byte getIntLowByte ( int value )
	{
		return ( byte ) ( value & 0xff );
	}

	public static byte [ ] getLongBytes ( long value )
	{
		byte [ ] bytes = new byte [ 8 ];
		bytes [ 0 ] = ( byte ) ( value >> 56 & 0xff );
		bytes [ 1 ] = ( byte ) ( value >> 48 & 0xff );
		bytes [ 2 ] = ( byte ) ( value >> 40 & 0xff );
		bytes [ 3 ] = ( byte ) ( value >> 32 & 0xff );
		bytes [ 4 ] = ( byte ) ( value >> 24 & 0xff );
		bytes [ 5 ] = ( byte ) ( value >> 16 & 0xff );
		bytes [ 6 ] = ( byte ) ( value >> 8 & 0xff );
		bytes [ 7 ] = ( byte ) ( value & 0xff );
		return bytes;
	}

	public static byte [ ] getShortBytes ( short value )
	{
		byte [ ] bytes = new byte [ 2 ];
		bytes [ 0 ] = ( byte ) ( value >> 8 & 0xff );
		bytes [ 1 ] = ( byte ) ( value & 0xff );
		return bytes;
	}

	public static long getLong ( byte [ ] bytes )
	{
		if ( bytes == null || bytes.length != 8 )
		{
			return 0;// throw new RuntimeException("类型不对!");
		}
		long v1 = bytes [ 0 ] & 0xff;
		long v2 = bytes [ 1 ] & 0xff;
		long v3 = bytes [ 2 ] & 0xff;
		long v4 = bytes [ 3 ] & 0xff;
		long v5 = bytes [ 4 ] & 0xff;
		long v6 = bytes [ 5 ] & 0xff;
		long v7 = bytes [ 6 ] & 0xff;
		long v8 = bytes [ 7 ] & 0xff;
		return ( v1 << 56 ) | ( v2 << 48 ) | ( v3 << 40 ) | ( v4 << 32 ) | ( v5 << 24 ) | ( v6 << 16 )
				| ( v7 << 8 ) | ( v8 & 0xff );
	}

}
